package com.kaxiu.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.kaxiu.config.redis.RedisService;
import com.kaxiu.persistent.entity.*;
import com.kaxiu.persistent.mapper.AccountMapper;
import com.kaxiu.service.IAccountLogService;
import com.kaxiu.service.IAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kaxiu.service.IRepairOrderService;
import com.kaxiu.service.ISysDicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;

import static com.kaxiu.config.CommonConstant.AccountConstant.*;
import static com.kaxiu.config.CommonConstant.DicKey.DIC_KEY_RAKE;

/**
 * <p>
 * 资金账户表 服务实现类
 * </p>
 * * 相关表：
 *      *      - account
 *      *          - 管理员账户 id = 1
 *      *          - 中间账户 id = 2
 *      *      - account_log
 * @author ly
 * @since 2019-08-04
 */
@Service
public class AccountServiceImpl extends ServiceImpl<AccountMapper, Account> implements IAccountService {

    @Autowired
    private AccountMapper mapper;

    @Autowired
    private IRepairOrderService repairOrderService;

    @Autowired
    private IAccountLogService logService;

    @Autowired
    private ISysDicService sysDicService;

    @Resource
    private RedisService redisService;

    @Override
    public Account getByUserId() {
        BasicUser user = redisService.getWxUser();
        return mapper.selectOne(Wrappers.<Account>lambdaQuery().eq(Account::getUserId, user.getId()));
    }

    /**
     * 1. 用户付款成功
     *      - 用户账户根据支付来源处理用户账户，暂时只有微信直接支付，所以用户account表不需修改
     *      - 中间账户入账这笔费用，作为临时保存款项处理， 其他账户暂时不会有这笔款项的记录
     *      - 日志表记录
     *          - 用户支出一笔款项
     *          - 中间账户入账
     * @param orders
     * @return
     */
    @Override
    @Transactional
    public Boolean successPayOrder(Orders orders) {
        //中间账户入账
        mapper.addAmount(ACCOUNT_MIDDLEMAN_ID, orders.getRealAmount());
        //日志记录 中间账户入账
        AccountLog middleLog = this.logInstance(
                ACCOUNT_MIDDLEMAN_ID,
                orders.getRemark(), orders.getRealAmount(),
                ACCOUNT_DIRECTION_IN,
                ACCOUNT_BIZ_TYPE_PAY, orders.getId(),
                orders.getTransactionId()
        );
        logService.save(middleLog);
        //日志记录 用户出账
        AccountLog userLog = this.logInstance(
                orders.getUserId(),
                orders.getRemark(), orders.getRealAmount(),
                ACCOUNT_DIRECTION_OUT,
                ACCOUNT_BIZ_TYPE_PAY, orders.getId(),
                orders.getTransactionId()
        );
        return logService.save(userLog);
    }

    /**
     * 2. 用户取消订单(维修完成就不让取消了)
     *      - 该笔订单至为取消状态
     *      — 中间账户出款，退款至微信账户
     *      - 日志表记录
     *          - 该笔订单日志记录至为取消
     *          - 中间账户出账
     * @param orders
     * @return
     */
    @Override
    @Transactional
    public Boolean calcleOrder(Orders orders) {
        AccountLog userLog = logService.getById(orders.getTransactionId(), orders.getUserId());
        if (userLog != null) {
            //该笔订单至为取消状态
            userLog.setStatus(ACCOUNT_LOG_STATUS_CALCLE);
            logService.updateById(userLog);
            //中间账户出账
            int minus = mapper.minusAmount(ACCOUNT_MIDDLEMAN_ID, orders.getRealAmount());
            if(minus > 0){
                //日志记录 中间账户出账
                AccountLog middleLog = this.logInstance(
                        ACCOUNT_MIDDLEMAN_ID,
                        orders.getRemark(), orders.getRealAmount(),
                        ACCOUNT_DIRECTION_OUT,
                        ACCOUNT_BIZ_TYPE_PAY, orders.getId(),
                        orders.getTransactionId()
                );
                logService.save(middleLog);
                //todo - 出账完成，微信负责退款，待完善
                return true;
            }
        }
        return false;
    }

    /**
     * 3. 维修完成
     *      - 中间账户出账
     *      - 管理员账户入账
     *      - 维修人员账户入账
     *      - 日志表
     *          -中间账户出账
     *          -管理员账户入账
     *          -维修人员账户入账
     * @param orders
     * @return
     */
    @Override
    @Transactional
    public Boolean overOrder(Orders orders) {
        //中间账户出账
        int minus = mapper.minusAmount(ACCOUNT_MIDDLEMAN_ID, orders.getRealAmount());
        if(minus > 0){
            //日志记录 中间账户出账
            AccountLog middleLog = this.logInstance(
                    ACCOUNT_MIDDLEMAN_ID,
                    orders.getRemark(), orders.getRealAmount(),
                    ACCOUNT_DIRECTION_OUT,
                    ACCOUNT_BIZ_TYPE_PAY, orders.getId(),
                    orders.getTransactionId()
            );
            logService.save(middleLog);
            // 管理员与维修人员入账
            SysDic dic = sysDicService.getDicByArr(new String[]{DIC_KEY_RAKE}).stream().findFirst().get();
            // 平台抽成百分比
            Double rate = Double.valueOf(dic.getDicValue());
            // 平台抽成计算
            BigDecimal rateVal = orders.getRealAmount().multiply(new BigDecimal(rate).divide(new BigDecimal(100)));
            // 维修人员剩余
            BigDecimal remind = orders.getRealAmount().subtract(rateVal);
            //管理员账户入账
            mapper.addAmount(ACCOUNT_ADMIN_ID, rateVal);
            //日志记录 管理员账户入账
            AccountLog adminLog = this.logInstance(
                    ACCOUNT_ADMIN_ID,
                    orders.getRemark(), rateVal,
                    ACCOUNT_DIRECTION_IN,
                    ACCOUNT_BIZ_TYPE_PAY, orders.getId(),
                    orders.getTransactionId()
            );
            logService.save(adminLog);
            //维修人员id
            Long maintenanceId = repairOrderService.getByOrderId(orders.getId()).getMaintenanceId();
            //维修人员账户入账
            mapper.addAmountByUserId(maintenanceId, remind);
            //日志 维修人员账户入账
            AccountLog maintenanceLog = this.logInstance(
                    maintenanceId,
                    orders.getRemark(), remind,
                    ACCOUNT_DIRECTION_IN,
                    ACCOUNT_BIZ_TYPE_PAY, orders.getId(),
                    orders.getTransactionId()
            );
            return logService.save(maintenanceLog);
        }
        return true;
    }

    /**
     * 4. 维修人员提现（审核成功）
     *      - 维修人员账户出账
     *      日志表
     *          - 维修人员账户出账
     * @return
     */
    @Override
    @Transactional
    public Boolean withdrawOrder() {
        //todo - 维修人员提现
        return true;
    }

    /**
     * 日志记录 生成日志对象
     * @param accountId 账户编号
     * @param remark    备注
     * @param amount    变动金额
     * @param direction 流向
     * @param bizType   变更业务类型
     * @param bizId     变更关联的业务id
     * @param transactionId 支付交易id
     * @return
     */
    private AccountLog logInstance(Long accountId, String remark, BigDecimal amount, Integer direction,
                                   Integer bizType, Long bizId, String transactionId) {
        AccountLog log = new AccountLog();
        log.setAccountId(accountId);
        log.setRemark(remark);
        log.setAmount(amount);
        log.setFundDirection(direction);
        log.setBizType(String.valueOf(bizType));
        log.setBizId(String.valueOf(bizId));
        log.setTransactionId(transactionId);
        return log;
    }

}
